// 封装复用逻辑
// 泛型：是一种模板，里面有一些占位符，编译器编译时会将占位符转换成对应的类型
// struct中定义类型
// enum使用泛型
// 把T放在impl关键词后，表示在类型T上实现方法：impl<T> Point<T>
// 只针对具体类型实现方法（其余类型没实现方法）：impl Point<i32>
// 泛型和具体代码运行速度一样

// trait（特征跟ts的interface类似）：告诉编译器某种类型具有哪些并且可以与其他类型共享的功能，抽象的定义共享行为
// trait bounds（约束）：泛型类型参数指定为实现了特定行为的类型： trait和impl配合使用
// trait定义：把方法签名放在一起，来定义时先某种目的所必须的一组行为。
// 关键字trait
// 只有方法签名，没有具体实现
// trait可以有多个方法，每个方法签名占一行，以；结尾
// 实现该trait的类型必须提供具体的方法实现
// trait有默认的实现，在impl中如果没有写方法的实现，那么就是使用默认的实现
// 指定多个trait可以使用+类似于ts的&，也可以在方法签名后使用where子句（类似c++）

// trait作为泛型

use::hello::TestTrait; // 这是引入了当前项目（hello）的lib中的方法
use::hello::Summary; // 这是引入了当前项目（hello）的lib中的方法

struct Point<T> {
    x: T
}

impl<T> Point<T> { // impl针对不具体的泛型要加上<T>指明是针对Point后面的T
    fn x(&self) -> &T {
        return &self.x
    }
}

impl Point<i32> {
    fn x1(&self) -> &i32 {
        return &self.x
    }
}

pub trait Summary1 {
    fn summary1(&self) -> String;
    fn summary2(&self) -> String;
}

// 使用trait作为泛型传入
fn testTrait1 (props: impl Summary) {
    props.summary1();
}

fn testTrait2<T: Summary> (props: T) {
    props.summary1();
}

fn main () {
    let testTrait = TestTrait {
        summary1: String::from("value"),
        summary2: String::from("value"),
    };
    testTrait.summary1();
    println!("hello world");
}